import Ajax from 'axios';

import * as Env from './../env';

import store from './../state';

import Auth from './../env/auth';

import * as Const from './const';

import {
    Actions
} from 'react-native-router-flux';

import * as userTypes from './../state/types/user';

import AsyncStorage from '@react-native-community/async-storage';

interface HookInterface {
    rejects: Array<Function>,
    resolves: Array<Function>
}

const Hooks: HookInterface = {
    rejects: [],
    resolves: []
}

const Instance = Ajax.create({
    timeout: 15 * 1000
})

const {
    request,
    response
} = Instance.interceptors;

request.use(async (config) => {
    config.baseURL = await Env.apiBaseUrl();
    config.headers[`Authorization`] = Auth.api;
    return config;
})

response.use(response => {
    return response.data
})

export const unLogin = async () => {
    await remove();
    store.dispatch({
        type: userTypes.userLoginOut
    })
    Actions.reset(`/`);
}

const getAccessToken = () => (
    AsyncStorage.getItem(Const.getToken)
)

const setAccessToken = (value: string) => (
    AsyncStorage.setItem(Const.getToken, value)
)

const getRefreshToken = (): Promise<any> => (
    AsyncStorage.getItem(Const.refreshToken)
)

const setRefreshToken = (value: string) => (
    AsyncStorage.setItem(Const.refreshToken, value)
)

//分发错误
const dispatchError = (data: any) => {
    Hooks.rejects.forEach((fn: Function) => fn(data));
    Hooks.rejects = [];
}

//分发成功
const dispatchSuccess = (data: any) => {
    Hooks.resolves.forEach((fn: Function) => fn(data))
    Hooks.resolves = [];
}

const formData = (token?: string) => {
    const fields: any = {
        refresh_token: token,
        grant_type: `refresh_token`
    }
    const Form = new FormData();

    Object.keys(fields).forEach(field => {
        Form.append(field, fields[field])
    })
    return Form;
}

//获取新的token
const newToken = async (token?: string): Promise<void> => {
    const form = (
        !!token ? formData(token) : null
    )
    try {
        const {
            access_token,
            refresh_token
        } = await Instance.post(
            `/auth`, form
        )
        dispatchSuccess(access_token);
        await setAccessToken(access_token);
        await setRefreshToken(refresh_token);
        return access_token;
    }
    catch (error) {
        const {
            response = {}
        } = error;
        const {
            data
        } = response;
        const _error = data ?
            data : Const.networkError;

        const {
            code = 0
        } = data || {};

        dispatchError(_error);

        //刷新失败,退出登录
        if (code === 10023) {
            await unLogin()
            return newToken();
        }
    }
}

//获取
export const get = (token?: string) => (
    new Promise(async (
        resolve: Function, reject: Function
    ) => {
        const _token = (
            await getAccessToken()
        )
        if (_token && !token) {
            return resolve(_token)
        }
        const {
            length
        } = Hooks.resolves;
        if (length <= 0) {
            newToken(token)
        }
        Hooks.rejects.push(reject);
        Hooks.resolves.push(resolve);
    })
)

//刷新
export const refresh = async () => {
    return get(await getRefreshToken());
}

//删除
export const remove = async () => {
    await setAccessToken('');
    await setRefreshToken('');
}